﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using Newtonsoft.Json;

namespace HigLabo.Net.Dropbox
{
    public partial class DropboxClient
    {
        private String GetResponseBodyText(String url)
        {
            return this.GetResponseBodyText(HttpMethodName.Get, url, null);
        }
        private String GetResponseBodyText(String url, DropboxCommand command)
        {
            return this.GetResponseBodyText(HttpMethodName.Get, url, command);
        }
        private String GetResponseBodyText(HttpMethodName methodName, String url)
        {
            return this.GetResponseBodyText(methodName, url, null);
        }
        private String GetResponseBodyText(HttpMethodName methodName, String url, DropboxCommand command)
        {
            String u = _Protocol.ToString().ToLower() + "://" + url;
            IDictionary<String, String> d = new Dictionary<String, String>();

            if (methodName == HttpMethodName.Put ||
                methodName == HttpMethodName.Delete)
            { throw new ArgumentException(); }

            if (command != null)
            {
                d = command.GetParameters();
            }
            var res = this.GetResponse(methodName, u, this._AccessToken, this._AccessTokenSecret, d);
            if (res.StatusCode != HttpStatusCode.OK)
            {
                throw new HttpResponseException(res);
            }
            return res.BodyText;
        }
        private Stream GetHttpWebResponse(HttpMethodName methodName, String url, DropboxCommand command)
        {
            String u = _Protocol.ToString().ToLower() + "://" + url;
            IDictionary<String, String> d = new Dictionary<string, string>();

            if (methodName == HttpMethodName.Put ||
                methodName == HttpMethodName.Delete)
            { throw new ArgumentException(); }

            if (command != null)
            {
                d = command.GetParameters();
            }
            var rs = this.GetHttpWebResponse(methodName, u, this._AccessToken, this._AccessTokenSecret, d);
            return rs.GetResponseStream();
        }
        private void Post(String url, UploadFileCommand command)
        {
            String u = _Protocol.ToString().ToLower() + "://" + url;
            var d = new Dictionary<String, String>();
            d["file"] = command.FileName;
            var cm = this.CreateHttpRequestCommand(HttpMethodName.Post, u, this.AccessToken, this.AccessTokenSecret, d);
            String boundary = UploadFileCommand.GetBoundaryString();
            cm.ContentType = "multipart/form-data; boundary=\"" + boundary + "\"";
            cm.SetBodyStream(command.CreatePostData(boundary));

            this.GetResponse(cm);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="consumerKey"></param>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public static AccessTokenInfo GetAccessTokenInfo(String consumerKey, String email, String password)
        {
            HttpClient cl = new HttpClient();
            var url = String.Format("https://{0}?oauth_consumer_key={1}&email={2}&password={3}"
                , DropboxApiUrl.Version0.Token, consumerKey, email, password);
            var d = JsonConvert.DeserializeObject<Dictionary<String, Object>>(cl.GetBodyText(url));
            return new AccessTokenInfo(d["token"].ToString(), d["secret"].ToString());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public AccountInfo GetAccountInfo()
        {
            return this.GetAccountInfo(null);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public AccountInfo GetAccountInfo(GetAccountCommand command)
        {
            var text = this.GetResponseBodyText(DropboxApiUrl.Version0.GetAccount, command);
            return new AccountInfo(text);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public String CreateAccount(CreateAccountCommand command)
        {
            return this.GetResponseBodyText(DropboxApiUrl.Version0.CreateAccount, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Metadata GetMetadata(GetMetadataCommand command)
        {
            String text = "";
            String url = "";

            if (command.Path.StartsWith("/") == true)
            {
                url = DropboxApiUrl.Version0.Metadata + command.Path;
            }
            else
            {
                url = DropboxApiUrl.Version0.Metadata + "/" + command.Path;
            }
            text = this.GetResponseBodyText(url, command);
            return new Metadata(text);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public Byte[] GetFile(String path)
        {
            Stream str = null;
            if (String.IsNullOrEmpty(path) == true) { throw new ArgumentException(); }
            if (path.StartsWith("/") == true)
            {
                str = this.GetHttpWebResponse(HttpMethodName.Get, DropboxApiUrl.Version0.Files + path, null);
            }
            else
            {
                str = this.GetHttpWebResponse(HttpMethodName.Get, DropboxApiUrl.Version0.Files + "/" + path, null);
            }
            return str.ToByteArray();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        public void UploadFile(UploadFileCommand command)
        {
            String url = "";
            if (String.IsNullOrEmpty(command.FolderPath) == true) { throw new ArgumentException(); }
            if (command.FolderPath.StartsWith("/") == true)
            {
                url = DropboxApiUrl.Version0.Files + command.FolderPath;
            }
            else
            {
                url = DropboxApiUrl.Version0.Files + "/" + command.FolderPath;
            }
            this.Post(url, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Byte[] GetThumbnails(GetThumbnailsCommand command)
        {
            Stream str = null;
            if (command.Path.StartsWith("/") == true)
            {
                str = this.GetHttpWebResponse(HttpMethodName.Get, DropboxApiUrl.Version0.Thumbnail + command.Path, command);
            }
            else
            {
                str = this.GetHttpWebResponse(HttpMethodName.Get, DropboxApiUrl.Version0.Thumbnail + "/" + command.Path, command);
            }
            return str.ToByteArray();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Metadata CopyFile(MoveFileCommand command)
        {
            var text = this.GetResponseBodyText(DropboxApiUrl.Version0.CopyFile, command);
            return new Metadata(text);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Metadata MoveFile(MoveFileCommand command)
        {
            var text = this.GetResponseBodyText(DropboxApiUrl.Version0.MoveFile, command);
            return new Metadata(text);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Metadata CreateFolder(CreateFolderCommand command)
        {
            var text = this.GetResponseBodyText(DropboxApiUrl.Version0.CreateFolder, command);
            return new Metadata(text);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        public void Delete(DeleteCommand command)
        {
            this.GetResponseBodyText(DropboxApiUrl.Version0.Delete, command);
        }
    }
}
